# -*- coding: utf-8 -*-
import email,sys,time,os,json,re,datetime
from imapclient import IMAPClient
from bs4 import BeautifulSoup

#定义字符创常量
#MAILFROM = '<AIS-EDR-SAAS@asiainfo-sec.com>'   # NEW SUBJECT '"AIS-EDR-SAAS" <ais-edr-saas@asiainfo-sec.com>'
MAILFROM = '"AIS-EDR-SAAS" <ais-edr-saas@asiainfo-sec.com>'
#163测试邮箱
#USERNAME = 'hh_octopus@163.com'    #163 邮箱账号
#HOSTNAME = 'imap.163.com'          #163 imap 域名
#PASSWD   = 'K*IRNRJAEUCTTMI*'W     #163 imap 授权码
#LOGOUT_SUCCESS = b'IMAP4rev1 Server logging out'  #163的logout电信的貌似不一样
#电信企业邮箱
USERNAME = 'master@octopussec.com'
HOSTNAME = 'imap-ent.21cn.com'
PASSWD   = 'Huqianjie@1'
LOGING_SUCCESS = b'LOGIN completed'
LOGOUT_SUCCESS = b'IMAP4 Server logging out'

#定义全局变量正则表达式
REGUserName     =  r"尊敬的 (.+?) 用户：<br/>"  
REGServerAddr   =  r"服务端地址：(.+?) <br/>"
REGLoginName    =  r"登录名：(.+?)<br/>" 
REGLoginPasswd  =  r"密码为：(.+?)<br/>" 
REGOTPkey       =  r"OTP密钥为：(.+?)<br/>"  
#REGWinDownload  =  r" windows客户端下载链接: (.+?)<br/>"   
REGWinDownload  =  r"<span> windows客户端下载链接: <a href=\"(.+?)\"" 
#定义全局变量
mail_dict = {'From':"", 'To':"", 'SUBJECT':"", 'Date':"", 'Payload':"",\
                'UserName':"", 'ServerAddr':"", 'LoginName':"", 'LoginPasswd':"",\
                'OTPkey':"", 'WinDownload':"", 'LinuxDownload':""}

windownload_list = []       #用来存储wget指定下载的列表


#打印格式化函数
def PRINT(string):
    print('>>>{},line:{},<<<    '\
    .format(time.strftime( "%b %d %Y %H:%M:%S",time.localtime(time.time()) )\
    ,sys._getframe().f_lineno)\
    ,end="")
    # /print('调用该函数的上级为{}'.format(sys._getframe(1).f_code.co_name))
    print(string)

#json到文件
def jsonPersist(filename, maildict):
    PRINT("-------------->jsonPersist begin---------->")
    with open(filename, "w") as json_file:
        assert json.dump(maildict, json_file, ensure_ascii=False) == None    #ensure_ascii=False 默认为True 则该文件的内容为unicode编码方式
    PRINT("-------------->jsonPersist done ---------->")

#创建目录
def makedir(path):
    #path=path.strip()
    #去除尾部 \ 符号
    isExists=os.path.exists(path)
    # 判断结果
    if not isExists:
        # 如果不存在则创建目录
        os.makedirs(path) 
        return True
    else:
        return False    

#填充mail_dict
def fill_mail(mail_dict, From, To, SUBJECT, Date, Payload,\
                UserName, ServerAddr, LoginName, LoginPasswd,\
                OTPkey, WinDownload, LinuxDownload=""):
    mail_dict['From']           =   From
    mail_dict['To']             =   To
    mail_dict['SUBJECT']        =   SUBJECT
    mail_dict['Date']           =   Date
    mail_dict['Payload']        =   Payload
    mail_dict['UserName']       =   UserName
    mail_dict['ServerAddr']     =   ServerAddr
    mail_dict['LoginName']      =   LoginName
    mail_dict['LoginPasswd']    =   LoginPasswd
    mail_dict['OTPkey']         =   OTPkey  
    mail_dict['WinDownload']    =   WinDownload        

#****************************************
#*****主函数 
#****************************************   
def main():
    PRINT(">>>>>>>>>>>>>>>main start<<<<<<<<<<<<<<<<<<<<")
    #服务器网址和邮箱和邮箱授权码##KWIRNRJAEUCTTMIW
    hostname = HOSTNAME
    username = USERNAME
    passwd = PASSWD
    server = IMAPClient(hostname, ssl= True)
    try:
        #登陆账号
        PRINT("SERVER LOGING")
        assert server.login(username, passwd) == LOGING_SUCCESS
        # 上传客户端身份信息
        server.id_({"name": "IMAPClient", "version": "2.3.1"})
        #导航目录的列表，'INBOX'，'草稿箱'、'已发送'等
        dictList = server.list_folders()
        #对收件箱只读  select_folder('INBOX', readonly=True) 设置只读不会改变对应的unseen状态 server.search([ u'UNSEEN'])
        info = server.select_folder('INBOX')
        #result = server.search([ u'SINCE', datetime.date(2022, 8, 1),u'UNSEEN'])  #u'UNSEEN',
        #result = server.search(['FROM', 'AIS-EDR-SAAS@asiainfo-sec.com', u'SINCE', datetime.date(2022, 9, 3)])
        result = server.search([ u'UNSEEN'])
        #result = server.search([u'SINCE', datetime.date(2022, 9, 1)])
        if(len(result) == 0):
            PRINT("No email for search!!!")
            sys.exit(1)
        PRINT("uid list len is "+str(len(result)) )
        PRINT(result)
        for uid in result:
            PRINT("======================"+str(uid)+"======================")
            massage = server.fetch(uid,['BODY[]'])
            mailBody = massage[uid][b'BODY[]']
            
            #邮件内容解析最里面那层是按字节来解析邮件主题内容,这个过程生成Message类型
            try :
                email_content = email.message_from_string(mailBody) #我看其他博主的都是拿到str类型的，如果这个时候拿到邮件的类型是str就用这个
            except TypeError:
                email_content = email.message_from_bytes(mailBody)  #但压力在我这，我没拿到str类型的，拿到的是bytes字节类型的，那就用字节解析吧
                #如果想知道字符集的可以在这先输出一下，查看结果里面的字符集是'utf-8'还是什么
            #发件人
            mail_from = email.header.make_header(email.header.decode_header(email_content['From']))
            PRINT('[debug]  mail from')
            PRINT(mail_from)
            if(mail_from == MAILFROM):      #发件人匹配则解析
                #收件人
                PRINT('[debug]  mail set seen')
                #server.set_flags(massage, b'\\Seen', silent=False)    #设置成已读!!!!!!
                mail_to = email.header.make_header(email.header.decode_header(email_content['To']))
                PRINT('[debug]  mail to')
                PRINT(mail_to)
                #标题
                subject = email.header.make_header(email.header.decode_header(email_content['SUBJECT']))
                PRINT('[debug]  mail subject')
                PRINT(subject)
                #收件日期
                envlope = (server.fetch(uid,['ENVELOPE']))[uid][b'ENVELOPE']
                dates = envlope.date
                PRINT('[debug]  mail dates')
                PRINT(dates)
                # 获取内容的type编码方式
                maintype = email_content.get_content_maintype()
                PRINT( maintype )
                if maintype == 'multipart':
                    for part in email_content.walk():      #用于遍历 mutipart 更好，下面一行失效在飞书中，outlook下一行可以
                    #for part in email_content.get_payload():
                        #获取邮件中的文本
                        if part.get_content_type() == 'text/html':
                            #取出正文内容并去掉前后的换行符、空格
                            #PRINT(part)
                            mail_content = part.get_payload(decode=True).strip()
                            try:
                                mail_content = mail_content.decode('utf-8')
                                mail_dict['Payload'] = mail_content
                                fill_mail(mail_dict, str(mail_from), str(mail_to), str(subject), str(dates), mail_content,\
                                        re.findall(REGUserName,mail_content)[0], re.findall(REGServerAddr,mail_content)[0],\
                                        re.findall(REGLoginName,mail_content)[0], re.findall(REGLoginPasswd,mail_content)[0],\
                                        re.findall(REGOTPkey,mail_content)[0], re.findall(REGWinDownload,mail_content)[0])
                                makedir(mail_dict['UserName'])      
                                jsonPersist(mail_dict['UserName']+'/'+ mail_dict['UserName']+'.json', mail_dict)
                                winlink = 'wget -c -O  ./'+mail_dict['UserName'] +'/AisEsmAgentSetup.exe'+' \"'+mail_dict['WinDownload']+'\"'
                                windownload_list.append(winlink)
                                #PRINT(winlink)
                                #os.system(winlink)
                            except UnicodeDecodeError:
                                PRINT('[error] decode error')
                                sys.exit(1)
                elif maintype == 'text':
                    mail_content = email_content.get_payload(decode=True).strip()
                    try:
                        mail_content = mail_content.decode('utf-8')
                        PRINT('[debug]  mail text payload')
                        #PRINT(mail_content)
                        fill_mail(mail_dict, str(mail_from), str(mail_to), str(subject), str(dates), mail_content,\
                                        re.findall(REGUserName,mail_content)[0], re.findall(REGServerAddr,mail_content)[0],\
                                        re.findall(REGLoginName,mail_content)[0], re.findall(REGLoginPasswd,mail_content)[0],\
                                        re.findall(REGOTPkey,mail_content)[0], re.findall(REGWinDownload,mail_content)[0])
                        makedir(mail_dict['UserName'])        
                        jsonPersist(mail_dict['UserName']+'/'+ mail_dict['UserName']+'.json', mail_dict)
                        #PRINT(mail_dict['WinDownload'])
                        winlink = 'wget -c -O  ./'+mail_dict['UserName'] +'/AisEsmAgentSetup.exe'+' \"'+mail_dict['WinDownload']+'\"'
                        windownload_list.append(winlink)
                        #PRINT(winlink)
                        #os.system(winlink)
                    except UnicodeDecodeError:
                        PRINT('[error] decode error')
                        sys.exit(1)

        PRINT("SERVER LOGOUT")              #同步完成email 即刻登出,下载放置后面来做
        assert server.logout() == LOGOUT_SUCCESS
        PRINT("SERVER LOGOUT SUCCESS")
        
        #成功登陆完成后使用存储的下载列表逐个下载
        PRINT("DOWNLOAD START")
        if(len(windownload_list) == 0):
            PRINT("length of download list is 0!")
            sys.exit(1)
        else:
            for links in windownload_list:
                os.system(links)    
        PRINT("DOWNLOAD OVER")        
        PRINT(">>>>>>>>>>>>>>>main over<<<<<<<<<<<<<<<<<<<<")

    except server.Error:
        print('Could not login')
        sys.exit(1)




#****************************************
#*****主程序 
#**************************************** 
if __name__ == '__main__':
    main()
